<template>
  <div>
    <div v-if="mode === 'DESIGN'">
      <div class="design">
        <i class="el-icon-plus"></i>
      </div>
      <p>{{ placeholder }} {{ sizeTip }}</p>
    </div>
    <template v-else>
      <div class="picture-card">
        <div class="picture-card-list">
          <div class="picture-card__item" v-for="(item, index) in _value" :key="item.fileId">
            <div class="picture-card__item-mask">
              <el-icon @click="handleRemove(index)"><Delete /></el-icon>
            </div>
            <el-image
              :src="item.fileUrl"
              fit="cover"
              preview-teleported
              :preview-src-list="[item.fileUrl]"
              v-if="multipartOssStore.loadingArr[item.fileId] === 100"
            ></el-image>
            <el-progress
              v-if="multipartOssStore.loadingArr[item.fileId] !== 100"
              type="circle"
              :percentage="multipartOssStore.loadingArr[item.fileId]"
            />
          </div>
          <div class="picture-card__item" style="border: 0">
            <el-upload
              ref="upload"
              action=""
              accept="image/*"
              :show-file-list="false"
              :multiple="maxSize > 0"
              :limit="maxSize"
              :before-upload="beforeUpload"
              :on-exceed="oneExceed"
              :http-request="customUpload"
              :on-error="onError"
            >
              <div class="upload-picture-card">
                <el-icon><Plus /></el-icon>
              </div>
            </el-upload>
          </div>
        </div>
        <div slot="tip" class="el-upload__tip">{{ placeholder }} {{ sizeTip }}</div>
      </div>
    </template>
  </div>
</template>

<script setup>
import { computed, ref, useAttrs, getCurrentInstance } from "vue";
import { dayjs } from "element-plus";
import { Plus, Delete } from "@element-plus/icons-vue";
import { fileReadRole, setACL, signatureUrl } from "@/utils/aliOssUpload";
import useMultipartOssStore from "@/store/modules/multipartOss";
import defaultConfig from "@/settings";

const { proxy } = getCurrentInstance();
const $attrs = useAttrs();
const props = defineProps({
  mode: {
    type: String,
    default: "DESIGN"
  },
  required: {
    type: Boolean,
    default: false
  },
  readonly: {
    type: Boolean,
    default: false
  },
  maxSize: {
    type: Number,
    default: 5
  },
  maxNumber: {
    type: Number,
    default: 10
  },
  modelValue: {
    type: Array,
    default: () => []
  },
  placeholder: {
    type: String,
    default: "请选择图片"
  }
});
const emit = defineEmits(["update:modelValue"]);
const multipartOssStore = useMultipartOssStore();

const sizeTip = computed(() => {
  return props.maxSize > 0 ? `| 每张图不超过${props.maxSize}MB` : "";
});
const _value = computed({
  get() {
    props.modelValue.forEach(item => {
      multipartOssStore.loadingArr[item.fileId] = 100;
    });
    return props.modelValue;
  },
  set(val) {
    emit("update:modelValue", val);
  }
});

const disabled = ref(false);
const uploadParams = ref({});

const beforeUpload = file => {
  if (props.maxSize <= 0) {
    proxy.$modal.msgError(`请设置正确的文件大小！`);
    return false;
  }
  const maxSize = file.size / 1024 / 1024 < props.maxSize;
  if (!maxSize) {
    proxy.$modal.msgError(`单个文件大小不能超过${props.maxSize}M!`);
    return false;
  }
  return true;
};
const oneExceed = files => {
  proxy.$modal.msgError(`最多上传${props.maxNumber}个文件`);
  return false;
};
const getSuffix = fileName => {
  return fileName.slice(fileName.lastIndexOf(".") + 1);
};
const getFileName = fileName => {
  return fileName.slice(0, fileName.lastIndexOf("."));
};
const fileToBlob = file => {
  return {
    fileId: file.uid,
    uid: file.uid,
    name: file.name,
    size: file.size,
    type: file.type,
    suffix: file.suffix,
    fileUrl: URL.createObjectURL(file)
  };
};
const customUpload = async option => {
  _value.value.push(fileToBlob(option.file));
  multipartOssStore.loadingArr[option.file.uid] = 0;
  const nowTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
  let file = option.file,
    fileName = option.file.name;
  fileName = `${getFileName(fileName)}-${nowTime}.${getSuffix(fileName)}`;
  file = new File([file], fileName, { type: file.type });
  let objName = `${defaultConfig.fileFolder}/${file.name}`;
  multipartOssStore
    .submit(objName, file, option.file.uid)
    .then(async res => {
      await setACL(objName, fileReadRole.publicRead);
      if ($attrs.fileReadRole === fileReadRole.publicRead) {
        const fileUrl = await signatureUrl(objName);
        res.fileUrl = fileUrl ? `${fileUrl}`.split("?")[0] : "";
      }
      res.fileId = option.file.uid;
      res.size = file.size;
      res.file = option.file;
      res.fileName = file.name;
      res.file.suffix = getSuffix(file.name);
      _value.value.some((item, index) => {
        if (item.fileId === res.fileId) {
          _value.value[index] = res;
          return true;
        }
      });
      emit("update:modelValue", _value.value);
    })
    .catch(err => {
      console.log(err);
      alert(JSON.stringify(err));
    });
};
const onError = () => {};
const handleRemove = index => {
  _value.value.splice(index, 1);
};
const handlePictureCardPreview = file => {
  console.log(file);
};
const handleDownload = file => {
  console.log(file);
};
</script>

<style lang="less" scoped>
@picture-card-size: 84px;
.design {
  i {
    padding: 10px;
    font-size: xx-large;
    background: white;
    border: 1px dashed #8c8c8c;
  }
}

.upload-picture-card {
  display: flex;
  justify-content: center;
  align-items: center;
  width: @picture-card-size;
  height: @picture-card-size;
  border: 1px solid #cdd0d6;
  background-color: #fafafa;
  overflow: hidden;
  /deep/.el-icon-plus {
    font-size: 28px;
    color: #909399;
  }
}
.picture-card {
  display: flex;
  display: -webkit-flex;
  flex-wrap: wrap;
  width: 100%;
  .picture-card-list {
    width: 100%;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(@picture-card-size, 1fr));
    grid-gap: 10px;
  }
  &__item {
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
    width: 100%;
    height: @picture-card-size;
    cursor: pointer;

    &:hover {
      .picture-card__item-mask {
        z-index: 999;
        background-color: rgba(0, 0, 0, 0.5);
      }
    }

    &-mask {
      display: flex;
      justify-content: center;
      align-items: center;
      position: absolute;
      width: 100%;
      height: 100%;
      z-index: -1;
      font-size: 20px;
      transition: background-color 0.3s;

      :deep(.el-icon) {
        color: #fff;

        & + .el-icon {
          margin-left: 10px;
        }
      }
    }

    :deep(.el-image) {
      width: 100%;
      height: 100%;
    }
  }
}

:deep(.el-progress-circle) {
  width: 84px !important;
  height: 84px !important;
}
</style>
